package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.db.api.FreezeApi;
import com.tanhua.dubbo.db.api.UserInfoApi;
import com.tanhua.dubbo.mongo.api.CommentApi;
import com.tanhua.dubbo.mongo.api.FocusUserApi;
import com.tanhua.dubbo.mongo.api.VideoApi;
import com.tanhua.model.db.Freeze;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.FocusUser;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.vo.CommentVo;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VideoVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.ibatis.builder.BuilderException;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class SmallVideosService {

    @DubboReference
    private VideoApi videoApi;

    @Autowired
    private FastFileStorageClient client; //从调度服务器获取，一个目标存储服务器，上传

    @Autowired
    private FdfsWebServer webServer;

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private CommentApi commentApi;

    @DubboReference
    private FreezeApi freezeApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private FocusUserApi focusUserApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    //@CacheEvict(value = "Videos" ,allEntries = true) //通用缓存
    public void saveVideo(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {


        Long userId = UserHolder.getUserId();

        //查询该用户否被冻结
        String key = Constants.USER_FREEZE+userId;
        Freeze freeze = freezeApi.findFreezeByUserId(userId);
        if (freeze != null) {
            UserInfo userInfo = userInfoApi.findById(userId);
            //获取从redis中获取的数据
            String freezeTime = redisTemplate.opsForValue().get(key);
            Integer freezingTime = freeze.getFreezingTime();
            if (freezeTime == null && freezingTime != 3) {
                userInfo.setUserStatus("1");
                userInfoApi.updateUserInfo(userInfo);
            }
            if (freezeTime != null) {
                if (userInfo.getUserStatus().equals("2") && freeze.getFreezingRange() == 2) {
                    throw new BusinessException(ErrorResult.freezeSpeakError());
                }
            }
        }

        // 1 视频上传到FastDFS中
        String filename = videoFile.getOriginalFilename();
        filename = filename.substring(filename.lastIndexOf(".") + 1);

        //上传
        StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), filename, null);

        // 保存位置+文件名
        String fullPath = storePath.getFullPath();

        String videoUrl = fullPath + webServer.getWebServerUrl();


        // 2 图片上传到阿里云中
        String picUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());

        //创建video对象 调用api保存
        Video video = new Video();
        video.setUserId(userId);
        video.setPicUrl(picUrl);
        video.setVideoUrl(videoUrl);
        video.setCreated(System.currentTimeMillis());
        video.setText("第一次测试");

        videoApi.saveVideo(video);
    }

    // 查询小视频列表
    //@Cacheable(value = "Videos",key = "T(com.tanhua.server.interceptor.UserHolder).getUserId()+'_'+#page+'_'+#page")////通用缓存
    public PageResult findVideos(Integer page, Integer pagesize) {

        System.out.println("从数据库中查询数据");
        //获得登录着id
        Long userId = UserHolder.getUserId();

        //从redis中获取小视频id
        String key = Constants.VIDEOS_RECOMMEND + userId;

        String value = redisTemplate.opsForValue().get(key);

        List<Video> list = new ArrayList<>();
        if (StringUtils.isEmpty(value)) {
            //不存在，从mongoDB中查询所有并返回
            list = videoApi.findAll(page, pagesize);
        } else {
            //存在 从redis中查询返回 ,当redis中的数据查询完接着从mongoDB中查询所有并返回
            String[] ids = value.split(",");

            list = videoApi.findByIds(ids, page, pagesize);
        }

        //查询的集合不存在 返回空数据
        if (list == null || list.size() <= 0) {
            return new PageResult();
        }

        List<Long> ids = CollUtil.getFieldValues(list, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids);


        List<VideoVo> vos = new ArrayList<>();
        for (Video video : list) {
            UserInfo userInfo = map.get(video.getUserId());

            VideoVo vo = VideoVo.init(userInfo, video);
            vos.add(vo);
        }


        return new PageResult(page, pagesize, 0l, vos);
    }

    //视频用户关注
    public void userFocus(Long focusId) {

        //获得登陆者id
        Long userId = UserHolder.getUserId();


        Boolean hash = focusUserApi.findById(userId, focusId);
        if (!hash) {
            FocusUser focusUser = new FocusUser();
            focusUser.setUserId(userId);
            focusUser.setFocusId(focusId);
            focusUser.setFocus(0);
            focusUser.setCreated(System.currentTimeMillis());
            focusUserApi.saveFocus(focusUser);
        } else {
            throw new BusinessException(ErrorResult.focusError());
        }


    }

    //视频用户关注 - 取消
    public void userUnFocus(Long focusId) {
        //获得登陆者id
        Long userId = UserHolder.getUserId();
        focusUserApi.findById(userId, focusId);

        Boolean hash = focusUserApi.findById(userId, focusId);
        if (hash) {
            focusUserApi.userUnFocus(userId, focusId);
        } else {
            throw new BusinessException(ErrorResult.disFocusError());
        }


    }
    //小视频点赞
    public Integer videoLike(String videoId) {
        Long userId = UserHolder.getUserId();
        Integer commentType = 1;
        Boolean hasLike = commentApi.hasComment(videoId, userId, commentType);
        if (hasLike){
            ErrorResult result = ErrorResult.likeError();
            throw  new BusinessException(result);
        }
        //创建小视频互动对象
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId)); // 设置小视频id
        comment.setCommentType(commentType); //设置互动类型
        comment.setUserId(userId); //设置点赞人id
        comment.setCreated(System.currentTimeMillis()); //设置点赞时间
        Integer likeCount = commentApi.saveVideoComment(comment);

        //保存到redis中
        String key = Constants.MOVEMENTS_INTERACT_KEY+videoId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY+userId;
        redisTemplate.opsForHash().put(key,hashKey,"1");
        return likeCount;
    }
    //小视频取消点赞
    public Integer videoDisLike(String videoId) {
        //获取点赞者id
        Long userId = UserHolder.getUserId();

        //设定commentType,点赞-->1
        int commentType = 1;

        //先查询该条动态"我"是否有点赞,返回值布尔
        Boolean hasComment = commentApi.hasComment(videoId, userId, commentType);

        if (!hasComment) { //若未点赞 返回错误信息
            throw new BusinessException(ErrorResult.disLikeError());
        }

        //点赞状态 则取消点赞 从mongDB数据库中删除
        Integer count = commentApi.dislikeVideo(videoId, userId, commentType);

        //从redis中删除
        String key = Constants.MOVEMENTS_INTERACT_KEY + videoId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().delete(key, hashKey);


        return count;
    }
    //查询评论列表
    public PageResult findAllComments(String videoId, Integer page, Integer pagesize) {
        //根据movementId获得评论list
        int commentType = 2;

        List<Comment> comments = commentApi.findAllComments(videoId, page, pagesize, commentType);

        //判断comments是否为空,
        if (comments == null || comments.size() <= 0) {

            return new PageResult();
        }

        List<Long> ids = CollUtil.getFieldValues(comments, "userId", Long.class);
        Map<Long, UserInfo> infoMap = userInfoApi.findByIds(ids);

        //创建 CommentVo的list集合
        List<CommentVo> vos = new ArrayList<>();
        for (Comment comment : comments) {

            UserInfo userInfo = infoMap.get(comment.getUserId());
            //封装
            CommentVo vo = CommentVo.init(userInfo, comment);

            vos.add(vo);
        }

        return new PageResult(page, pagesize, 0l, vos);
    }
    //发布评论
    public void saveComments(String videoId, String comment) {
        //1.获得登录中的userId
        Long userId = UserHolder.getUserId();


        //查询该用户否被冻结
        String key = Constants.USER_FREEZE+userId;
        Freeze freeze = freezeApi.findFreezeByUserId(userId);
        if (freeze != null) {
            UserInfo userInfo = userInfoApi.findById(userId);
            //获取从redis中获取的数据
            String freezeTime = redisTemplate.opsForValue().get(key);
            Integer freezingTime = freeze.getFreezingTime();
            if (freezeTime == null && freezingTime != 3) {
                userInfo.setUserStatus("1");
                userInfoApi.updateUserInfo(userInfo);
            }
            if (freezeTime != null) {
                if (userInfo.getUserStatus().equals("2") && freeze.getFreezingRange() == 2) {
                    throw new BusinessException(ErrorResult.freezeSpeakError());
                }
            }
        }

        int commentType = 2;

        //创建Comment对象
        Comment comment1 = new Comment();
        //传入数据
        comment1.setPublishId(new ObjectId(videoId));
        comment1.setCommentType(commentType);
        comment1.setContent(comment);
        comment1.setUserId(userId);
        comment1.setCreated(System.currentTimeMillis());
        //调用方法保存,返回该动态的总评论数
        Integer count = commentApi.saveVideoComment(comment1);
        System.out.println(comment);
    }
    //小视频的评论点赞
    public void commentsLike(Object commentsId) {
        Comment comment = commentApi.findComments(commentsId);
        comment.setLikeCount(comment.getLikeCount());
        commentApi.addCommentsLike(comment,commentsId);
    }
    //小视频的评论 取消点赞
    public void commentsDisLike(ObjectId commentsId) {
        Comment comment = commentApi.findComments(commentsId);
        comment.setLikeCount(comment.getLikeCount());
        commentApi.addCommentsDisLike(comment,commentsId);
    }
}
